﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

//TODO: test

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// This is a special line detector.
    /// It starts at the center of a picture.(default)
    /// Then rays will be send out (like a sun)
    /// Each ray is compared with every pixel hitted by it.
    /// If enough pixels are hit (default: all pixels) there is a line.
    /// </summary>
    public class RadialScan : BaseImageFilter
    {
        protected int m_nThreshold = 7;
        List<KeyValuePair<Point, Point>> aLine = new List<KeyValuePair<Point, Point>>();
        /// <summary>
        /// Initializes a new instance of the <see cref="RadialScan"/> class.
        /// </summary>
        public RadialScan()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="RadialScan"/> class.
        /// </summary>
        /// <param name="_radialScan">The _radial scan.</param>
        internal RadialScan(RadialScan _radialScan)
        { 
        }

        /// <summary>
        /// Radial Scan
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            UnsafeBitmap bitmapCloned = (UnsafeBitmap)_bitmap.Clone();
            int nWidth = _bitmap.Width;
            int nHeight = _bitmap.Height;

            Color color = Color.Transparent;
            Color colorLast = Color.Transparent;
            int nGray = 0;
            int nGraySum = 0;

            int nXMiddle = nWidth / 2;
            int nYMiddle = nHeight / 2;

            //walk around the circle, and find lines....
            double c = 0;
            double x = 0;
            double dStep = 1;
            double y = 0;
            int i = 0;
            int r = (int)Math.Sqrt(nWidth * nHeight);
            
            List<KeyValuePair<Point, Point>> aLineTemp = new List<KeyValuePair<Point, Point>>(); 
            
            for (i = 0; i < 360; i++)
            {
                color = Color.Blue;
                x = (int)Math.Round(x + Math.Sin(i) * r);
                y = (int)Math.Round(y + Math.Cos(i) * r);
                IEnumerable<Point> aPoint = Bresenham.RenderLine(new Point(nXMiddle, nYMiddle), new Point((int)x, (int)y));

                int nLinePointCount = aPoint.Count<Point>();
                int nTempLinePointCount = 0;

                bool bStart = false;
                bool bValid = false;
                Point ptStart = Point.Empty;
                Point ptEnd = Point.Empty;
                Point ptCurrent = Point.Empty; 
                foreach (Point point in aPoint)
                {
                    colorLast = color;
                    if (point.X < 0 || point.X > nWidth - 1 || point.Y < 0 || point.Y > nHeight - 1)
                    {
                        continue;
                    }
                    if (x < 0 || x > nWidth - 1 || y < 0 || y > nHeight - 1)
                    {
                        continue;
                    }
                    
                    color = bitmapCloned.GetPixel((int)x, (int)y);
                    if (color != colorLast)
                    {
                        int n1 = 0;
                    }
                    if (ColorFunctions.DistanceSquared(colorLast, color) < m_nThreshold) //if (color == Definitions.Red)
                    {
                        if (!bStart)
                        {
                            bStart = true;
                            ptStart = point;
                        }
                        bValid = true;
                    }
                    else
                    {
                        bValid = false;
                    }
                    if (bStart && !bValid)
                    {
                        ptEnd = point;
                        aLineTemp.Add(new KeyValuePair<Point, Point>(ptStart, ptEnd));
                        bStart = false;
                    }
                }
                if (bStart == true && bValid == true)
                {
                    aLineTemp.Add(new KeyValuePair<Point, Point>(ptStart, ptCurrent));
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new RadialScan(this);
        }
    }
}
